package org.offsync.async

import java.nio.channels.{ServerSocketChannel => JavaServerSocketChannel}
import java.net.InetSocketAddress
import java.net.InetAddress
import java.nio.channels.SelectionKey
import org.offsync.util.DisposableBase
import org.offsync.util.DisposableProxy
import org.offsync.nio.ServerSocketChannel
import org.offsync.rich._

case class AsyncServerSocket(private val channel: JavaServerSocketChannel) extends DisposableBase {
  def accept(
      asyncService: AsyncService,
      hostAddress: InetAddress,
      port: Int)(callback: AsyncResult[AsyncSocket] => AsyncReturn) = {
    // Bind the server socket to the specified address and port
    channel.socket.bind(new InetSocketAddress(hostAddress, port));

    // Register the server socket channel, indicating an interest in 
    // accepting new connections
    channel.onReady(asyncService, SelectionKey.OP_ACCEPT) { () =>
      val socketChannel = channel.accept()
      socketChannel.configureBlocking(false)
      callback(AsyncResult(new AsyncSocket(socketChannel)))
    };
  }
  
  protected override def onDispose(): Unit = {
    try channel.close() catch { case e => }
    
    super.onDispose()
  }
}

object AsyncServerSocket {
  def open(): AsyncServerSocket = {
    val serverSocketChannel = JavaServerSocketChannel.open()
    serverSocketChannel.configureBlocking(false)
    return AsyncServerSocket(serverSocketChannel)
  }
}
